package org.unidata.mdm.rest.search.configuration;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.RuntimeDelegate;

import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.apache.cxf.Bus;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.openapi.OpenApiFeature;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.unidata.mdm.rest.search.service.SearchRestApplication;
import org.unidata.mdm.rest.search.service.SearchRestService;
import org.unidata.mdm.rest.system.exception.RestExceptionMapper;
import org.unidata.mdm.rest.system.service.ReceiveInInterceptor;
import org.unidata.mdm.rest.system.util.OpenApiMetadataFactory;
import org.unidata.mdm.system.configuration.AbstractConfiguration;

/**
 * @author Mikhail Mikhailov on Mar 5, 2020
 */
@Configuration
public class SearchRestConfiguration extends AbstractConfiguration {
    /**
     * The ID.
     */
    private static final ConfigurationId ID = () -> "SEARCH_REST_CONFIGURATION";
    /**
     * {@inheritDoc}
     */
    @Override
    protected ConfigurationId getId() {
        return ID;
    }

    @Bean
    public Application searchRestApplication() {
        return new SearchRestApplication();
    }

    @Bean
    public SearchRestService searchRestService() {
        return new SearchRestService();
    }

    @Bean
    public Server server(
            final Bus cxf,
            final Application searchRestApplication,
            final JacksonJaxbJsonProvider jacksonJaxbJsonProvider,
            final RestExceptionMapper restExceptionMapper,
            final ReceiveInInterceptor receiveInInterceptor,
            final SearchRestService searchRestService) {

        JAXRSServerFactoryBean jaxrsServerFactoryBean = RuntimeDelegate.getInstance()
                .createEndpoint(searchRestApplication, JAXRSServerFactoryBean.class);

        final OpenApiFeature searchOpenApiFeature = OpenApiMetadataFactory.openApiFeature(
                "Unidata Search API",
                "Unidata Search REST API operations",
                searchRestApplication, cxf,
                "org.unidata.mdm.rest.search.service");

        jaxrsServerFactoryBean.setProviders(Arrays.asList(jacksonJaxbJsonProvider, restExceptionMapper));
        jaxrsServerFactoryBean.setFeatures(List.of(searchOpenApiFeature));
        jaxrsServerFactoryBean.setInInterceptors(Collections.singletonList(receiveInInterceptor));
        jaxrsServerFactoryBean.setServiceBeans(Arrays.asList(searchRestService));

        return jaxrsServerFactoryBean.create();
    }
}
